<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>OAuth 2.0 认证授权详解 - 技术小馆</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        :root {
            --primary: #3B82F6;
            --primary-dark: #2563EB;
            --secondary: #10B981;
            --dark: #1F2937;
            --light: #F3F4F6;
            --gray: #9CA3AF;
        }
        
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
            background-color: #f9fafb;
        }
        
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', Georgia, serif;
            font-weight: 600;
            color: #111827;
        }
        
        .hero {
            background: linear-gradient(135deg, #3B82F6 0%, #1D4ED8 100%);
            color: white;
        }
        
        .card {
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
            border-radius: 0.5rem;
            overflow: hidden;
            background: white;
        }
        
        .card:hover {
            transform: translateY(-4px);
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
        }
        
        .code-block {
            font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            background-color: #1E293B;
            color: #F8FAFC;
            border-radius: 0.375rem;
            overflow-x: auto;
        }
        
        .highlight {
            background-color: rgba(59, 130, 246, 0.1);
            padding: 0.2rem 0.4rem;
            border-radius: 0.25rem;
            font-weight: 500;
        }
        
        .table-container {
            overflow-x: auto;
        }
        
        table {
            border-collapse: collapse;
            width: 100%;
            background: white;
        }
        
        th, td {
            padding: 0.75rem 1rem;
            text-align: left;
            border-bottom: 1px solid #E5E7EB;
        }
        
        th {
            background-color: #F3F4F6;
            font-weight: 600;
        }
        
        .quote {
            border-left: 4px solid var(--primary);
            background-color: #F8FAFC;
            padding: 1rem;
            font-style: italic;
        }
        
        .flow-chart {
            min-height: 300px;
            background: white;
            border-radius: 0.5rem;
            padding: 1.5rem;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero py-16 md:py-24 px-4 md:px-8 text-center">
        <div class="max-w-4xl mx-auto">
            <h1 class="text-4xl md:text-5xl font-bold mb-4">OAuth 2.0 认证授权协议</h1>
            <p class="text-xl md:text-2xl opacity-90 mb-8">开放标准的安全授权框架，让你的应用轻松实现第三方登录</p>
            <div class="flex justify-center space-x-4">
                <a href="#what-is-oauth" class="bg-white text-blue-600 hover:bg-blue-50 px-6 py-3 rounded-lg font-medium transition duration-300">了解更多</a>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <main class="max-w-6xl mx-auto px-4 md:px-8 py-12">
        <!-- What is OAuth -->
        <section id="what-is-oauth" class="mb-16">
            <div class="flex items-center mb-6">
                <i class="fas fa-lock text-blue-500 text-2xl mr-3"></i>
                <h2 class="text-3xl font-bold">OAuth是什么</h2>
            </div>
            
            <div class="grid md:grid-cols-2 gap-8">
                <div class="card p-6">
                    <p class="text-lg mb-4">OAuth的英文全称是Open Authorization，它是一种<strong>开放认证授权协议</strong>，要授权方和被授权方遵守这个协议去写代码提供服务，那双方就是实现了OAuth协议。</p>
                    
                    <div class="flex flex-col md:flex-row gap-4 mt-6">
                        <div class="flex-1 p-4 bg-blue-50 rounded-lg">
                            <h3 class="font-bold text-blue-600 mb-2 flex items-center">
                                <i class="fas fa-user-check mr-2"></i>认证
                            </h3>
                            <p>验证用户的身份，比如账号登录，指纹识别，人脸识别等。</p>
                        </div>
                        <div class="flex-1 p-4 bg-green-50 rounded-lg">
                            <h3 class="font-bold text-green-600 mb-2 flex items-center">
                                <i class="fas fa-shield-alt mr-2"></i>授权
                            </h3>
                            <p>对用户进行访问控制，比如判断用户是否被允许做某件事情。</p>
                        </div>
                    </div>
                    
                    <div class="mt-6 p-4 bg-yellow-50 border-l-4 border-yellow-400 rounded-r-lg">
                        <p class="font-medium">OAuth目前共有2个版本，2007年12月的1.0版（之后有一个修正版1.0a）和2010年4月的2.0版。2.0是一个新的设计，协议简单清晰，目前被Google, Yahoo, Microsoft, Facebook等广泛使用。</p>
                    </div>
                </div>
                
                <div class="flow-chart">
                    <div class="mermaid">
                        graph LR
                            A[客户端] -->|1. 授权请求| B[资源所有者]
                            B -->|2. 授权许可| A
                            A -->|3. 授权许可| C[授权服务器]
                            C -->|4. 访问令牌| A
                            A -->|5. 访问令牌| D[资源服务器]
                            D -->|6. 受保护资源| A
                    </div>
                </div>
            </div>
        </section>
        
        <!-- OAuth 2.0 Use Cases -->
        <section class="mb-16">
            <div class="flex items-center mb-6">
                <i class="fas fa-cogs text-blue-500 text-2xl mr-3"></i>
                <h2 class="text-3xl font-bold">OAuth2.0有什么用</h2>
            </div>
            
            <div class="card p-6 mb-8">
                <p class="text-lg">简单概括，就是用于第三方在用户授权下调取平台对外开放接口获取用户相关信息。</p>
                <p class="mt-4">OAuth引入了一个授权环节来解决上述问题。第三方应用请求访问受保护资源时，资源服务器在获准资源用户授权后，会向第三方应用颁发一个访问令牌(AccessToken)。该访问令牌包含资源用户的授权访问范围、授权有效期等关键属性。第三方应用在后续资源访问过程中需要一直持有该令牌，直到用户主动结束该次授权或者令牌自动过期。</p>
            </div>
            
            <div class="grid md:grid-cols-3 gap-6">
                <div class="card p-6 hover:border-blue-400">
                    <div class="text-blue-500 text-3xl mb-4">
                        <i class="fas fa-sign-in-alt"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-2">第三方登录</h3>
                    <p>允许用户使用已有账户(如Google, Facebook)登录你的应用，无需创建新账号</p>
                </div>
                
                <div class="card p-6 hover:border-blue-400">
                    <div class="text-blue-500 text-3xl mb-4">
                        <i class="fas fa-exchange-alt"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-2">API访问控制</h3>
                    <p>让你的应用安全访问用户在第三方服务中的数据，如获取Gmail联系人</p>
                </div>
                
                <div class="card p-6 hover:border-blue-400">
                    <div class="text-blue-500 text-3xl mb-4">
                        <i class="fas fa-share-alt"></i>
                    </div>
                    <h3 class="text-xl font-bold mb-2">跨应用共享</h3>
                    <p>用户可授权应用间数据共享，如将Dropbox文件保存到Google Drive</p>
                </div>
            </div>
        </section>
        
        <!-- OAuth 2.0 Grant Types -->
        <section class="mb-16">
            <div class="flex items-center mb-6">
                <i class="fas fa-key text-blue-500 text-2xl mr-3"></i>
                <h2 class="text-3xl font-bold">OAuth2.0授权模式</h2>
            </div>
            
            <div class="grid md:grid-cols-2 lg:grid-cols-5 gap-4 mb-8">
                <div class="card p-4 text-center hover:shadow-md">
                    <div class="text-blue-500 text-2xl mb-2">
                        <i class="fas fa-qrcode"></i>
                    </div>
                    <h3 class="font-bold">授权码模式</h3>
                    <p class="text-sm text-gray-600">最常用的模式</p>
                </div>
                
                <div class="card p-4 text-center hover:shadow-md">
                    <div class="text-blue-500 text-2xl mb-2">
                        <i class="fas fa-window-maximize"></i>
                    </div>
                    <h3 class="font-bold">简化模式</h3>
                    <p class="text-sm text-gray-600">为web浏览器设计</p>
                </div>
                
                <div class="card p-4 text-center hover:shadow-md">
                    <div class="text-blue-500 text-2xl mb-2">
                        <i class="fas fa-user-lock"></i>
                    </div>
                    <h3 class="font-bold">密码模式</h3>
                    <p class="text-sm text-gray-600">Resource Owner Password Credentials</p>
                </div>
                
                <div class="card p-4 text-center hover:shadow-md">
                    <div class="text-blue-500 text-2xl mb-2">
                        <i class="fas fa-server"></i>
                    </div>
                    <h3 class="font-bold">客户端模式</h3>
                    <p class="text-sm text-gray-600">为后台api调用设计</p>
                </div>
                
                <div class="card p-4 text-center hover:shadow-md">
                    <div class="text-blue-500 text-2xl mb-2">
                        <i class="fas fa-puzzle-piece"></i>
                    </div>
                    <h3 class="font-bold">扩展模式</h3>
                    <p class="text-sm text-gray-600">自定义模式</p>
                </div>
            </div>
            
            <div class="card p-6">
                <h3 class="text-xl font-bold mb-4">OAuth 2.0 核心角色</h3>
                
                <div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
                    <div class="p-4 border rounded-lg">
                        <h4 class="font-bold text-blue-600 mb-2">Resource Owner</h4>
                        <p>资源所有者，即代表授权客户端访问本身资源信息的用户，也就是应用场景中的"开发者A"</p>
                    </div>
                    
                    <div class="p-4 border rounded-lg">
                        <h4 class="font-bold text-blue-600 mb-2">Authorization Server</h4>
                        <p>授权服务器，验证用户身份，然后为客户端派发资源访问令牌</p>
                    </div>
                    
                    <div class="p-4 border rounded-lg">
                        <h4 class="font-bold text-blue-600 mb-2">Resource Server</h4>
                        <p>资源服务器，托管受保护的用户账号信息，比如QQ,百度</p>
                    </div>
                    
                    <div class="p-4 border rounded-lg">
                        <h4 class="font-bold text-blue-600 mb-2">Client</h4>
                        <p>客户端，即代表意图访问受限资源的第三方应用</p>
                    </div>
                </div>
            </div>
        </section>
        
        <!-- Baidu Login Example -->
        <section class="mb-16">
            <div class="flex items-center mb-6">
                <i class="fab fa-baidu text-blue-500 text-2xl mr-3"></i>
                <h2 class="text-3xl font-bold">使用百度账号登录</h2>
            </div>
            
            <div class="card p-6 mb-8">
                <div class="flex flex-col md:flex-row gap-6">
                    <div class="flex-1">
                        <h3 class="text-xl font-bold mb-4">1. 申请应用</h3>
                        <ol class="list-decimal pl-5 space-y-2">
                            <li>注册百度开发者账号：<a href="https://passport.baidu.com/v2/?reg&u=http%3A%2F%2Fdeveloper.baidu.com%2F&tpl=dev" class="text-blue-600 hover:underline" target="_blank">百度Passport</a>。如果已有则忽略该步骤，直接进入第二步。</li>
                            <li>登录百度开发者中心：<a href="http://developer.baidu.com/" class="text-blue-600 hover:underline" target="_blank">百度开发者中心</a></li>
                        </ol>
                        
                        <h3 class="text-xl font-bold mt-6 mb-4">2. 创建第三方授权应用</h3>
                        <ol class="list-decimal pl-5 space-y-2">
                            <li>进入百度开发者控制台应用管理页面：<a href="http://developer.baidu.com/console#app/project" class="text-blue-600 hover:underline" target="_blank">应用管理</a></li>
                            <li>单击"创建工程"，开始创建应用。</li>
                        </ol>
                    </div>
                    
                    <div class="flex-1 grid grid-cols-3 gap-2">
                        <img src="https://cdn.nlark.com/yuque/0/2025/png/21449790/1741349607378-d59e4742-09c6-4293-91fe-b712c2f2deb7.png" alt="百度开发者中心" class="rounded border">
                        <img src="https://cdn.nlark.com/yuque/0/2025/png/21449790/1741349607430-47a74d0b-e34c-467d-b6ef-0273029492d4.png" alt="创建工程" class="rounded border">
                        <img src="https://cdn.nlark.com/yuque/0/2025/png/21449790/1741349607492-109845fd-2ce7-42ff-865f-114e4eda08b7.png" alt="应用信息" class="rounded border">
                    </div>
                </div>
            </div>
            
            <div class="grid md:grid-cols-2 gap-8">
                <div class="card p-6">
                    <h3 class="text-xl font-bold mb-4">3. 引导用户登录</h3>
                    <p>API文档：<a href="http://developer.baidu.com/wiki/index.php?title=docs/oauth" class="text-blue-600 hover:underline" target="_blank">百度OAuth文档</a></p>
                    
                    <div class="mt-4 code-block p-4 rounded-lg">
                        <pre><code>http://openapi.baidu.com/oauth/2.0/authorize?
    response_type=code&
    client_id=YOUR_CLIENT_ID&
    redirect_uri=YOUR_REGISTERED_REDIRECT_URI&
    scope=email&
    display=popup</code></pre>
                    </div>
                    
                    <table class="w-full mt-4">
                        <thead>
                            <tr>
                                <th>参数名</th>
                                <th>是否必须</th>
                                <th>含义</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>client_id</td>
                                <td>必须</td>
                                <td>你应用的API Key</td>
                            </tr>
                            <tr>
                                <td>response_type</td>
                                <td>必须</td>
                                <td>必须参数，此值固定为"code"</td>
                            </tr>
                            <tr>
                                <td>redirect_uri</td>
                                <td>必须</td>
                                <td>你应用填写的回调地址</td>
                            </tr>
                            <tr>
                                <td>scope</td>
                                <td>非必须</td>
                                <td>授予一个应用的一系列数据访问操作权限</td>
                            </tr>
                            <tr>
                                <td>display</td>
                                <td>非必须</td>
                                <td>标识不同形式的客户端所对应的不同展现形式的授权页面</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                
                <div class="">
                    <img src="https://cdn.nlark.com/yuque/0/2025/png/21449790/1741349607548-3e29f20b-c1ef-4891-9628-596c849e72ba.png" alt="百度授权页面" class="rounded-lg shadow-md w-full">
                </div>
            </div>
        </section>
        
        <!-- JustAuth Section -->
        <section class="mb-16">
            <div class="flex items-center mb-6">
                <i class="fas fa-code text-blue-500 text-2xl mr-3"></i>
                <h2 class="text-3xl font-bold">JustAuth介绍</h2>
            </div>
            
            <div class="card p-6">
                <div class="flex flex-col md:flex-row gap-8">
                    <div class="flex-1">
                        <p class="text-lg mb-4">JustAuth，如你所见，它仅仅是一个<strong>第三方授权登录</strong>的<strong>工具类库</strong>，它可以让我们脱离繁琐的第三方登录SDK，让登录变得<strong>So easy!</strong></p>
                        <p>官网: <a href="https://justauth.wiki/" class="text-blue-600 hover:underline" target="_blank">https://justauth.wiki/</a></p>
                        
                        <div class="mt-6">
                            <h3 class="text-xl font-bold mb-4">JustAuth特点</h3>
                            <ol class="list-disc pl-5 space-y-2">
                                <li><strong>全</strong>：已集成十多家第三方平台（国内外常用的基本都已包含），仍然还在持续扩展中</li>
                                <li><strong>简</strong>：API就是奔着最简单去设计的，尽量让您用起来没有障碍感</li>
                            </ol>
                        </div>
                    </div>
                    
                    <div class="flex-1">
                        <h3 class="text-xl font-bold mb-4">关键概念</h3>
                        
                        <div class="space-y-4">
                            <div>
                                <h4 class="font-bold text-blue-600">clientId</h4>
                                <p>客户端身份标识符（应用id），一般在申请完Oauth应用后，由<strong>第三方平台颁发</strong>，唯一</p>
                            </div>
                            
                            <div>
                                <h4 class="font-bold text-blue-600">clientSecret</h4>
                                <p>客户端密钥，一般在申请完Oauth应用后，由<strong>第三方平台颁发</strong></p>
                            </div>
                            
                            <div>
                                <h4 class="font-bold text-blue-600">redirectUri</h4>
                                <p><strong>开发者项目中的有效api地址</strong>。用户在确认第三方平台授权（登录）后，第三方平台会重定向到该地址，并携带code等参数</p>
                            </div>
                            
                            <div>
                                <h4 class="font-bold text-blue-600">state</h4>
                                <p>用来保持授权会话流程完整性，防止CSRF攻击的安全的随机的参数，由<strong>开发者生成</strong></p>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="mt-8">
                    <h3 class="text-xl font-bold mb-4">Java代码示例</h3>
                    
                    <div class="code-block p-4 rounded-lg">
                        <pre><code>@Controller
public class JustAutoController {

    @RequestMapping("/render")
    public void renderAuth(HttpServletResponse response) throws IOException {
        System.out.println("loign....");
        AuthRequest authRequest = getAuthRequest();
        String authorize = authRequest.authorize(AuthStateUtils.createState());
        System.out.println(authorize);
        response.sendRedirect(authorize);
    }

    @RequestMapping("/callback")
    @ResponseBody
    public Object login(AuthCallback callback) {
        System.out.println("callback:code:" + callback.getCode() + ",state:" + callback.getState());
        AuthRequest authRequest = getAuthRequest();
        AuthResponse authResp = authRequest.login(callback);

        if (authResp.ok()) {
            AuthUser data = (AuthUser) authResp.getData();
            String username = data.getUsername();
            System.out.println(username);
            return username;
        }else{
            return "登录失败，跳转到登录页面";
        }
        return "callback";
    }

    private AuthRequest getAuthRequest() {
        return new AuthBaiduRequest(AuthConfig.builder()
                .clientId("IVh2e8u6rNd9Xx5r29UGwB3P")
                .clientSecret("qqufMxlAmHtgCGtscDr9NS2D5OtYbdxM")
                .redirectUri("http://localhost:8080/callback")
                .scopes(Arrays.asList(AuthBaiduScope.SUPER_MSG.getScope()))
                .build());
    }
}</code></pre>
                    </div>
                    
                    <div class="mt-4 p-4 bg-blue-50 rounded-lg">
                        <p class="font-medium">依赖配置：</p>
                        <div class="code-block mt-2 p-4 rounded-lg">
                            <pre><code>&lt;dependency&gt;
    &lt;groupId&gt;me.zhyd.oauth&lt;/groupId&gt;
    &lt;artifactId&gt;JustAuth&lt;/artifactId&gt;
    &lt;version&gt;1.16.1&lt;/version&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
    &lt;groupId&gt;cn.hutool&lt;/groupId&gt;
    &lt;artifactId&gt;hutool-http&lt;/artifactId&gt;
    &lt;version&gt;5.1.0&lt;/version&gt;
    &lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white py-8">
        <div class="max-w-6xl mx-auto px-4 md:px-8 text-center">
            <div class="text-xl font-bold mb-2">技术小馆</div>
            <div class="text-gray-400 hover:text-white transition duration-300">
                <a href="http://www.yuque.com/jtostring" target="_blank">http://www.yuque.com/jtostring</a>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: false,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>